﻿#region Using Statements
using System;
using GameBase.Screens;
using GameBase.Sprites;
using Microsoft.Xna.Framework;
using StarFox.ScreenComponents;
#endregion

namespace StarFox.Screens
{
    /// <summary>
    /// Introductory screen before gameplay.
    /// </summary>
    public class IntroScreen : StarFoxScreen
    {
        #region Screen Transitions

        /// <summary>
        /// Makes the Screen transition to visible state.
        /// </summary>
        public override void Show()
        {
            string[] playList = { "02_GAMEPLAY_THEME" };
            PlayList.Start(playList);
            PlayList.Repeat = true;

            base.Show();
        }

        #endregion

        #region Initialization

        /// <summary>
        /// Initializes a new instance of this class.
        /// </summary>
        /// <param name="screenManager">The ScreenManager that this Screen is associated to.</param>
        public IntroScreen(ScreenManager screenManager)
            : base(screenManager)
        {
            Name = "IntroScreen";
        }

        /// <summary>
        /// Called when the Screen needs to be initialized.
        /// </summary>
        public override void Initialize()
        {
            Components2D.Add(new IntroMessage(this));

            base.Initialize();
        }

        #endregion
    }

    #region Introductory Message

    /// <summary>
    /// Introductory message.
    /// </summary>
    public class IntroMessage : ScreenComponent2D
    {
        #region Fields

        SpriteSheet spriteSheet;

        // message
        Rectangle dstRectMsg;
        Point initPosMsg;
        Point endPosMsg;

        bool toPlay = false;
        readonly TimeSpan totalPlayTime = TimeSpan.FromMilliseconds(1000);

        #endregion

        #region Screen Transitions

        bool toVisible = false;
        bool toHidden = false;

        float trTime = 0.0f;

        /// <summary>
        /// Makes the ScreenComponent2D transition to visible state.
        /// </summary>
        public override void Show()
        {
            toVisible = true;
        }

        /// <summary>
        /// Makes the ScreenComponent2D transition to hidden state.
        /// </summary>
        public override void Hide()
        {
            toHidden = true;
        }

        #endregion

        #region Constructor

        /// <summary>
        /// Initializes a new instance of this class.
        /// </summary>
        /// <param name="screen">The Screen that this ScreenComponent2D is associated to.</param>
        public IntroMessage(Screen screen)
            : base(screen)
        {
            spriteSheet = Game.Content.Load<SpriteSheet>(ContentSettings.GetAsset("MSG_SPRITES"));

            Rectangle auxRect = spriteSheet.SourceRectangle("STAGE_1_1");
            dstRectMsg = new Rectangle(0, 0, (int)(auxRect.Width * Screen.Scale), (int)(auxRect.Height * Screen.Scale));
            initPosMsg = new Point(-dstRectMsg.Width, (int)((Screen.Height - dstRectMsg.Height) * 0.5f));
            endPosMsg = new Point((int)((Screen.Width - dstRectMsg.Width) * 0.5f), initPosMsg.Y);
            dstRectMsg.Location = initPosMsg;
        }

        #endregion

        #region Update

        /// <summary>
        /// Called when the ScreenComponent2D needs to be updated.
        /// </summary>
        /// <param name="gameTime">Time elapsed since the last call to this method.</param>
        public override void Update(GameTime gameTime)
        {
            #region Screen Transition

            if (toVisible)
            {
                // update item positions
                float auxTrTime = 1.0f - (float)Math.Pow(1.0f - trTime, 2);
                dstRectMsg.X = initPosMsg.X + (int)(Math.Abs(initPosMsg.X - endPosMsg.X) * auxTrTime);

                // update transition timer
                float trDelta = (float)(gameTime.ElapsedGameTime.TotalMilliseconds / Time.TotalMilliseconds);
                trTime += trDelta;
                trTime = MathHelper.Clamp(trTime, 0.0f, 1.0f);
                if (trTime == 1.0f) { toVisible = false; toPlay = true; trTime = 0.0f; }
            }
            else if (toHidden)
            {
                // update item positions
                float auxTrTime = 1.0f - (float)Math.Pow(1.0f - trTime, 2);
                dstRectMsg.X = endPosMsg.X - (int)(Math.Abs(initPosMsg.X - endPosMsg.X) * auxTrTime);

                // update transition timer
                float trDelta = (float)(gameTime.ElapsedGameTime.TotalMilliseconds / Time.TotalMilliseconds);
                trTime += trDelta;
                trTime = MathHelper.Clamp(trTime, 0.0f, 1.0f);
                if (trTime == 1.0f) { toHidden = false; trTime = 0.0f; }
            }

            #endregion

            #region Play

            if (toPlay)
            {
                float trDelta = (float)(gameTime.ElapsedGameTime.TotalMilliseconds / totalPlayTime.TotalMilliseconds);
                trTime += trDelta;
                trTime = MathHelper.Clamp(trTime, 0.0f, 1.0f);
                if (trTime == 1.0f) { toPlay = false; trTime = 0.0f; Screen.ScreenManager.Clear(new GamePlayScreen(Screen.ScreenManager)); }
            }

            #endregion
        }

        #endregion

        #region Draw

        /// <summary>
        /// Called when the ScreenComponent2D needs to be drawn.
        /// </summary>
        /// <param name="gameTime">Time elapsed since the last call to this method.</param>
        public override void Draw(GameTime gameTime)
        {
            // message
            SpriteBatch.Draw(spriteSheet.Texture, dstRectMsg, spriteSheet.SourceRectangle("STAGE_1_1"), Color.Yellow);
        }

        #endregion
    }

    #endregion
}
